/*
  This file is a part of Angry IP Scanner source code,
  see http://www.angryip.org/ for more information.
  Licensed under GPLv2.
 */
package net.azib.ipscan.gui.actions;

import net.azib.ipscan.config.LoggerFactory;
import net.azib.ipscan.config.Platform;
import net.azib.ipscan.core.UserErrorException;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * The cross-platform terminal launcher
 * 
 * @author Anton Keks
 */
public class TerminalLauncher {
	
	static final Logger LOG = LoggerFactory.getLogger();
	
	private static final int UNKNOWN = -1;
	private static final int XTERM = 0;
	private static final int GNOME = 1;
	private static final int XFCE = 2;
	private static final int KDE = 3;
	/** caches last working terminal type */
	private static int workingTerminal = UNKNOWN;
	
	/**
	 * Launches the execString in the terminal.
	 * Supports Linux/Unix, MacOS, and Windows
	 * @param execString the command to launch
	 * @param workingDir the working directory (or null)
	 */
	public static void launchInTerminal(String execString, File workingDir) {

		try {
			if (Platform.WINDOWS) {
				// generate a command file :-)
				File batFile = File.createTempFile("launch", ".cmd");
				batFile.deleteOnExit();
				FileWriter writer = new FileWriter(batFile);
				writer.write("@rem This is a temporary file generated by Angry IP Scanner\n" +
						     "@start cmd /k " + execString);
				writer.close();
				
				Runtime.getRuntime().exec(batFile.getAbsolutePath(), null, workingDir);
			}
			else
			if (Platform.MAC_OS) {
				Runtime.getRuntime().exec(new String[] {"osascript", "-e", "tell application \"Terminal\" to do script \"" + execString + "\""}, null, workingDir);
			}
			else { // assume Linux or other Unix
				
				if (workingTerminal == UNKNOWN) {
					detectWorkingTerminal();
				}
				
				// run detected terminal program
				switch (workingTerminal) {
					case GNOME:
						Runtime.getRuntime().exec(new String[] {"gnome-terminal", "-x", "bash", "-c", execString + ";bash"}, null, workingDir);
						break;
					case XFCE:
						Runtime.getRuntime().exec(new String[] {"xfce4-terminal", "-x", "sh", "-c", execString + ";sh"}, null, workingDir);
						break;
					case KDE:
						Runtime.getRuntime().exec(new String[] {"konsole", "-e", "bash", "-c", execString + ";bash"}, null, workingDir);
						break;
					default: // XTERM
						Runtime.getRuntime().exec(new String[] {"xterm", "-e", "sh", "-c", execString + ";sh"}, null, workingDir);
				}
			}
		}
		catch (Exception e) {
			// log and display the error
			LOG.log(Level.WARNING, "openTerminal.failed", e);

			// if this is the first time, fall back to XTERM
			if (workingTerminal != XTERM) {
				workingTerminal = XTERM;
				launchInTerminal(execString, workingDir);
			}
			else {
				// even XTERM doesn't work...
				throw new UserErrorException("openTerminal.failed", execString);
			}
		}
	}

	private static void detectWorkingTerminal() throws InterruptedException, IOException {
		if (Runtime.getRuntime().exec(new String[] {"pidof", "nautilus"}).waitFor() == 0) {
			workingTerminal = GNOME;
		}
		else
		if (Runtime.getRuntime().exec(new String[] {"pidof", "xfce4-session", "xfwm4", "Thunar", "xfdesktop"}).waitFor() == 0) {
			workingTerminal = XFCE;
		}
		else
		if (Runtime.getRuntime().exec(new String[] {"pidof", "dcopserver"}).waitFor() == 0) {
			workingTerminal = KDE;
		}
		else {
			workingTerminal = XTERM;
		}
	}
}
